﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;

namespace QSearcher.QCrawler
{
    public abstract class IAnalyzer
    {
        public class AnalyzeSource : BizLayer.AnalyzeSource
        {
            public string File { set; get; }
        }

        public class AnalyzeResult : BizLayer.AnalyzeResult
        {
        }

        public abstract string Name { get; }
        public abstract string Remark { get; }
        public abstract AnalyzeResult Analyze(AnalyzeSource source);

        private AnalyzeSource GetSource()
        {
            var res = BizLayer.Self.GetAnalyzeSource(this.Name);
            return new AnalyzeSource()
            {
                Code = res.Code,
                Msg = res.Msg,
                ID = res.ID,
                Url = res.Url,
            };
        }

        private void SetResult(AnalyzeResult result)
        {
            BizLayer.Self.SendAnalyzeResult(result);
        }

        public void Run(int index)
        {
            PrintLog("开始请求数据.......");
            var source = GetSource();
            PrintLog("请求数据完成.");
            if (source.Code != 0)
            {
                PrintLog("未请求到有效数据.");
                return;
            }
            source.File = "Requests" + Path.DirectorySeparatorChar + Crawler.UrlToPath(source.Url);
            PrintLog("请求到有效数据.");
            PrintLog("开始分析数据.......");
            var result = Analyze(source);
            PrintLog("完成数据分析.");
            PrintLog("反馈分析数据.......");
            SetResult(result);
            PrintLog("完成分析数据反馈.");
        }

        public static List<IAnalyzer> GetAnalyzers()
        {
            string dir = "Analyzers";
            if (!Directory.Exists(dir)) return new List<IAnalyzer>();
            string[] files = Directory.GetFiles(dir, "*.dll");
            if (files.Length <= 0) return new List<IAnalyzer>();
            var res = new List<IAnalyzer>();
            foreach (var file in files)
            {
                var assembly = Assembly.LoadFrom(new FileInfo(file).FullName);
                var types = assembly.GetTypes();
                foreach (var t in types)
                {
                    var isFind = t.BaseType.FullName == typeof(IAnalyzer).FullName;
                    if (!isFind) continue;
                    var analyzer = Activator.CreateInstance(t) as IAnalyzer;
                    res.Add(analyzer);
                }
            }
            return res;
        }

        #region 提供给分析器的API
        #region v0.1
        [Obsolete("提供的信息不完善故舍去")]
        private List<string> GetRegs(string regStr, string text)
        {
            var res = new HashSet<string>();
            Regex reg = new Regex(regStr, RegexOptions.IgnoreCase);
            MatchCollection match = reg.Matches(text);
            foreach (Match m in match)
            {
                var href = m.Groups["val"].Value;
                href = href.Trim();
                if (href == "") continue;
                var val = href.ToLower();
                if (val == "#") continue;
                if (val.IndexOf("javascript") == 0) continue;
                res.Add(href);
            }
            return new List<string>(res);
        }
        [Obsolete("提供的信息不完善故舍去,请使用GetTagAs替代")]
        protected List<string> GetHrefs(string html)
        {
            string reg = @"(?is)<a[^>]*?href=(['""\s]?)(?<val>[^'""\s]*)\1[^>]*?>";
            return GetRegs(reg, html);
        }
        [Obsolete("提供的信息不完善故舍去,请使用GetTagImgs替代")]
        protected List<string> GetImgs(string html)
        {
            string reg = @"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<val>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>";
            return GetRegs(reg, html);
        }
        #endregion

        #region v1.0
        protected string GetTitle(string html)
        {
            Regex reg = new Regex(@"\<title[^\>]*\>\s*(?<val>.*?)\s*\</title\>", RegexOptions.IgnoreCase);
            try
            {
                var match = reg.Match(html);
                return match.Groups["val"].Value;
            }
            catch { return ""; }
        }

        public class ATager
        {
            public string Html { set; get; }
            public string Href { set; get; }
            public string Text { set; get; }
            public string Title { set; get; }
            public string Type { set; get; }

            public static ATager From(string html)
            {
                ATager result = new ATager();
                return result;
            }
        }

        protected List<ATager> GetTagAs(string html)
        {
            Regex reg = new Regex(@"<a\s*[^>]*>([\s\S]+?)</a>", RegexOptions.IgnoreCase);
            List<ATager> result = new List<ATager>();
            var aTags = reg.Matches(html);
            foreach (Match aTag in aTags)
            {
                var strATag = aTag.Value;
                result.Add(ATager.From(strATag));
            }
            return result;
        }

        public class ImgTager
        {
            public string Html { set; get; }
            public string Alt { set; get; }
            public string Src { set; get; }
            public string Title { set; get; }
        }

        protected List<ImgTager> GetTagImgs(string html)
        {
            return null;
        }
        #endregion

        protected void PrintLog(string log)
        {
            FrmCrawler.T.SendMsg("[" + Name + "]分析器:"+log);
        }
        #endregion 
    }
}
